//
// Created by 11510 on 2024/6/23.
//

#include "TextQuery.h"
#include <cctype> // 用于std::isalnum
#include <sstream>
#include <fstream>

using std::cin;
using std::cerr;
using std::cout;
using std::endl;
using std::istringstream;
using std::ifstream;

void replaceNonAlnumWithSpace(std::string& str) {
    for (char& ch : str) {
        if (!std::isalnum(ch) && ch != '-') {
            ch = ' ';
        }
    }
}

/**
 * 构造的时候就把文件全部读入，并建立每个单词和行的映射
 * @param is
 */
TextQuery::TextQuery(ifstream &is) : file(new vector<string>) {
    file->reserve(10000);

    string text;

    while (getline(is, text)) {
        file->push_back(text); // 保存此行

        int n = file->size() - 1; // 当前行号

        replaceNonAlnumWithSpace(text);
        istringstream line(text); // separate the line into words

        string word;

//        注意：这里建立的是每个单词和行的映射！！！！！！
        while (line >> word) {
//            TODO 此处需要判断是否为一个单词
            auto &lines = wm[word];
            /**
             * 第二个参数是指针，此处理解为指向指针的指针，所以需要判断
             */
            if (!lines) {
                lines.reset(new set<line_no>);
            }
            lines->insert(n);
        }
    }
}


QueryResult TextQuery::query(const string &sought) const {

    // 如果找到则返回一个指向此set的集合
    static shared_ptr<set<line_no>> nodata(new set<line_no>);

    // []会将单词添加到map中，所以用find()
    auto loc = wm.find(sought);

    if (loc == wm.end()) {
        return QueryResult(sought, nodata, file); // 返回空集合，注意此处要加静态
    }

    /**
     * 这里形参传的是智能指针的拷贝
     */
    return QueryResult(sought, loc->second, file);
}